#include "mainwidget.h"

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    logDialogInit();
    settingsLoad(SETTINGS_FILENAME);

    widgetInit();
    serialPortInit();

    emit log("+++ Start +++");
    serialPortOpen();
}

MainWidget::~MainWidget()
{
    serialPortClose();
    settingsSave(SETTINGS_FILENAME);

    emit log("--- End ---");
    emit save(LOGMSG_FILENAME);
    delete m_pLogDialog;
}

/*void MainWidget::log(const QString msg)
{
    m_pLogDialog->log(msg);
}*/

void MainWidget::keyPressEvent(QKeyEvent *e)
{
    //serialPortWrite(e->text().toLocal8Bit());
    static Qt::KeyboardModifiers _kms = (Qt::ControlModifier | Qt::AltModifier);
    if ((QApplication::keyboardModifiers() & _kms) == _kms) {
        if (Qt::Key_D == e->key()) {
            qDebug() << " Correct Key ";
            m_pLogDialog->show();
        }
    }
}

void MainWidget::buttonClicked(int id)
{
    qDebug() << "buttonClicked : " << id;

    switch (id) {
    case IdButtonSerialPort:
    {
        SerialPortDialog dlg(&m_serialPortData);
        int result = dlg.exec();
        if (result) {
            serialPortClose();
            serialPortOpen();
        }
    }
        break;
    case IdButtonExit:
        qApp->quit();
        break;
    default:
        if (IdButtonRelay <= id) {
            /*qint32 bId = (id - IdButtonRelay) / NUM_RELAY_MAX;
            qint32 rId = (id - IdButtonRelay) % NUM_RELAY_MAX;

            if (m_listBoardData[bId].status[rId]) {
                m_listBoardData[bId].status[rId] = 0;
            } else {
                m_listBoardData[bId].status[rId] = 1;
            }
            QString text;
            text.sprintf("%d%d - %d", bId, rId, m_listBoardData[bId].status[rId]);
            m_pButtonGroup->button(id)->setText(text);

            emit log(QString("buttonClicked(%1%2 - %3)").arg(bId).arg(rId).arg(m_listBoardData[bId].status[rId]));*/
        }
        break;
    }
}

void MainWidget::logDialogInit()
{
    m_pLogDialog = new LogDialog;
    connect(this, SIGNAL(log(const QString)), m_pLogDialog, SLOT(log(const QString)));
    connect(this, SIGNAL(save(const QString)), m_pLogDialog, SLOT(save(const QString)));
}

void MainWidget::settingsLoad(const QString fileName)
{
    QSettings settings(fileName, QSettings::IniFormat);

    settings.beginGroup("BoardData");
    int numBoard = settings.value("numBoard", NUM_BOARD_DEF).toInt();
    qDebug() << "numBoard : " << numBoard;
    settings.endGroup();

    for (int b=0; b<numBoard; b++) {
        settings.beginGroup(QString("Board%1").arg(b));
        qDebug() << "+++Board" << b;
        BoardData boardData;
        /*typedef struct
        {
            qint32  id;
            QString name;
            qint32  type;
            qint32  numRelay;
        } BoardData;*/
        boardData.id = settings.value("id", b).toInt();
        qDebug() << "boardData.id : " << boardData.id;
        boardData.name = settings.value("name", QString::number(b)).toString();
        qDebug() << "boardData.name : " << boardData.name;
        boardData.type = settings.value("type", 0).toInt();
        qDebug() << "boardData.type : " << boardData.type;
        boardData.numRelay = settings.value("numRelay", NUM_RELAY_DEF).toInt();
        qDebug() << "boardData.numRelay : " << boardData.numRelay;
        for (int r=0; r<boardData.numRelay; r++) {
            settings.beginGroup(QString("Relay%1").arg(r));
            qDebug() << " +++Relay" << r;
            /*typedef struct
            {
                qint32      boardId;
                qint32      relayId;
                QString     name;
                qint32      groupId;
                qint32      pushDelay;  // [sec]
                qint32      numAlarm;
                AlarmData   alarm[NUM_ALARM_MAX];
            } RelayData;*/
            boardData.relay[r].boardId = settings.value("boardId", b).toInt();
            qDebug() << " relay.boardId : " << boardData.relay[r].boardId;
            boardData.relay[r].relayId = settings.value("relayId", r).toInt();
            qDebug() << " relay.relayId : " << boardData.relay[r].relayId;
            boardData.relay[r].name = settings.value("name", QString::number(r)).toString();
            qDebug() << " relay.name : " << boardData.relay[r].name;
            boardData.relay[r].groupId = settings.value("groupId", -1).toInt();
            qDebug() << " relay.groupId : " << boardData.relay[r].groupId;
            boardData.relay[r].pushDelay = settings.value("pushDelay", 0).toInt();
            qDebug() << " relay.pushDelay : " << boardData.relay[r].pushDelay;
            boardData.relay[r].numAlarm = settings.value("numAlarm", 0).toInt();
            qDebug() << " relay.numAlarm : " << boardData.relay[r].numAlarm;
            for (int a=0; a<boardData.relay[r].numAlarm; a++) {
                settings.beginGroup(QString("Alarm%1").arg(a));
                qDebug() << "  +++Alarm" << a;
                /*typedef struct
                {
                    qint32  hour;
                    qint32  minute;
                    qint32  action;
                } AlarmData;*/
                boardData.relay[r].alarm[a].hour = settings.value("hour", 0).toInt();
                qDebug() << "  alarm.hour : " << boardData.relay[r].alarm[a].hour;
                boardData.relay[r].alarm[a].minute = settings.value("minute", 0).toInt();
                qDebug() << "  alarm.minute : " << boardData.relay[r].alarm[a].minute;
                boardData.relay[r].alarm[a].action = settings.value("action", 0).toInt();
                qDebug() << "  alarm.action : " << boardData.relay[r].alarm[a].action;
                qDebug() << "  ---Alarm" << a;
                settings.endGroup();
            }
            qDebug() << " ---Relay" << r;
            settings.endGroup();
        }
        m_listBoardData.append(boardData);
        qDebug() << "---Board" << b;
        settings.endGroup();
    }

    settings.beginGroup("SerialPortData");
    m_serialPortData.name = settings.value("name", "").toString();
    qDebug() << "m_serialPortData.name : " << m_serialPortData.name;
    m_serialPortData.baudRate = settings.value("baudRate", 115200).toInt();
    qDebug() << "m_serialPortData.baudRate : " << m_serialPortData.baudRate;
    m_serialPortData.dataBits = settings.value("dataBits", 8).toInt();
    qDebug() << "m_serialPortData.dataBits : " << m_serialPortData.dataBits;
    m_serialPortData.parity = settings.value("parity", 0).toInt();
    qDebug() << "m_serialPortData.parity : " << m_serialPortData.parity;
    m_serialPortData.stopBits = settings.value("stopBits", 0).toInt();
    qDebug() << "m_serialPortData.stopBits : " << m_serialPortData.stopBits;
    m_serialPortData.flowControl = settings.value("flowControl", 0).toInt();
    qDebug() << "m_serialPortData.flowControl : " << m_serialPortData.flowControl;
    settings.endGroup();
}

void MainWidget::settingsSave(const QString fileName)
{
    QSettings settings(fileName, QSettings::IniFormat);

    settings.beginGroup("BoardData");
    settings.setValue("numBoard", m_listBoardData.size());
    settings.endGroup();

    for (int b=0; b<m_listBoardData.size(); b++) {
        settings.beginGroup(QString("Board%1").arg(b));
        BoardData boardData = m_listBoardData.at(b);
        /*typedef struct
        {
            qint32  id;
            QString name;
            qint32  type;
            qint32  numRelay;
        } BoardData;*/
        settings.setValue("id", boardData.id);
        settings.setValue("name", boardData.name);
        settings.setValue("type", boardData.type);
        settings.setValue("numRelay", boardData.numRelay);
        for (int r=0; r<boardData.numRelay; r++) {
            settings.beginGroup(QString("Relay%1").arg(r));
            /*typedef struct
            {
                qint32      boardId;
                qint32      relayId;
                QString     name;
                qint32      groupId;
                qint32      pushDelay;  // [sec]
                qint32      numAlarm;
                AlarmData   alarm[NUM_ALARM_MAX];
            } RelayData;*/
            settings.setValue("boardId", boardData.relay[r].boardId);
            settings.setValue("relayId", boardData.relay[r].relayId);
            settings.setValue("name", boardData.relay[r].name);
            settings.setValue("groupId", boardData.relay[r].groupId);
            settings.setValue("pushDelay", boardData.relay[r].pushDelay);
            settings.setValue("numAlarm", boardData.relay[r].numAlarm);
            for (int a=0; a<boardData.relay[r].numAlarm; a++) {
                settings.beginGroup(QString("Alarm%1").arg(a));
                /*typedef struct
                {
                    qint32  hour;
                    qint32  minute;
                    qint32  action;
                } AlarmData;*/
                settings.setValue("hour", boardData.relay[r].alarm[a].hour);
                settings.setValue("minute", boardData.relay[r].alarm[a].minute);
                settings.setValue("action", boardData.relay[r].alarm[a].action);
                settings.endGroup();
            }
            settings.endGroup();
        }
        settings.endGroup();
    }

    settings.beginGroup("SerialPortData");
    settings.setValue("name", m_serialPortData.name);
    settings.setValue("baudRate", m_serialPortData.baudRate);
    settings.setValue("dataBits", m_serialPortData.dataBits);
    settings.setValue("parity", m_serialPortData.parity);
    settings.setValue("stopBits", m_serialPortData.stopBits);
    settings.setValue("flowControl", m_serialPortData.flowControl);
    settings.endGroup();
}

void MainWidget::widgetInit()
{
    setWindowTitle(tr("CubeControl"));
    setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);
    resize(800, 600);

    QGridLayout *mainLayout = new QGridLayout;
    setLayout(mainLayout);
    //mainLayout->setSizeConstraint(QLayout::SetFixedSize);
    //mainLayout->setSpacing(20);

    m_pButtonGroup = new QButtonGroup;
    connect(m_pButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(buttonClicked(int)));

    qint32 maxCol = 0;
    QString text;
    for (int i=0; i<m_listBoardData.size(); i++) {
        QLabel *labelBoard = new QLabel(m_listBoardData[i].name);
        labelBoard->setAlignment(Qt::AlignCenter);
        mainLayout->addWidget(labelBoard, i, 0);

        for (int j=0; j<m_listBoardData[i].numRelay; j++) {
            text.sprintf("%d%d - 0", i, j);
            QPushButton *buttonRelay = new QPushButton(text);
            m_pButtonGroup->addButton(buttonRelay, (IdButtonRelay + (NUM_RELAY_MAX*i) + j));
            mainLayout->addWidget(buttonRelay, i, (1 + j));
        }

        if (maxCol < m_listBoardData[i].numRelay) {
            maxCol = m_listBoardData[i].numRelay;
        }
    }

    mainLayout->addWidget(new QLabel, (m_listBoardData.size() + 1), 0);

    QPushButton *buttonSerialPort = new QPushButton(tr("SerialPort"));
    m_pButtonGroup->addButton(buttonSerialPort, IdButtonSerialPort);
    mainLayout->addWidget(buttonSerialPort, (m_listBoardData.size() + 2), (maxCol - 1));

    QPushButton *buttonExit = new QPushButton(tr("Exit"));
    m_pButtonGroup->addButton(buttonExit, IdButtonExit);
    mainLayout->addWidget(buttonExit, (m_listBoardData.size() + 2), maxCol);
}

void MainWidget::serialPortInit()
{
    m_pSerialPort = new QSerialPort(this);
    connect(m_pSerialPort, SIGNAL(error(QSerialPort::SerialPortError)), this,
            SLOT(serialPortError(QSerialPort::SerialPortError)));
    connect(m_pSerialPort, SIGNAL(readyRead()), this, SLOT(serialPortRead()));
}

void MainWidget::serialPortOpen()
{
    emit log(QString("serialPortOpen(%1)").arg(m_serialPortData.name));
    m_pSerialPort->setPortName(m_serialPortData.name);
    if (m_pSerialPort->open(QIODevice::ReadWrite)) {
        if (m_pSerialPort->setBaudRate(m_serialPortData.baudRate)
                && m_pSerialPort->setDataBits((QSerialPort::DataBits)m_serialPortData.dataBits)
                && m_pSerialPort->setParity((QSerialPort::Parity)m_serialPortData.parity)
                && m_pSerialPort->setStopBits((QSerialPort::StopBits)m_serialPortData.stopBits)
                && m_pSerialPort->setFlowControl((QSerialPort::FlowControl)m_serialPortData.flowControl))
        {
            // ...
            return;
        }
        else
        {
            emit log(QString("Error(%1)").arg(m_pSerialPort->errorString()));
            QMessageBox::critical(this, tr("Error"), m_pSerialPort->errorString());
        }
    }
    else
    {
        emit log(QString("Error(%1)").arg(m_pSerialPort->errorString()));
        QMessageBox::critical(this, tr("Error"), m_pSerialPort->errorString());
    }
    serialPortClose();
}

void MainWidget::serialPortClose()
{
    if (m_pSerialPort->isOpen()) {
        emit log("serialPortClose()");
        m_pSerialPort->close();
    }
}

void MainWidget::serialPortWrite(const QByteArray &data)
{
    if (m_pSerialPort->isOpen()) {
        m_pSerialPort->write(data);
    }
}

void MainWidget::serialPortRead()
{
    QByteArray data = m_pSerialPort->readAll();
    emit log(QString(data));
}

void MainWidget::serialPortError(QSerialPort::SerialPortError error)
{
    if (error == QSerialPort::ResourceError) {
        emit log(QString("Critical Error(%1)").arg(m_pSerialPort->errorString()));
        QMessageBox::critical(this, tr("Critical Error"), m_pSerialPort->errorString());
        serialPortClose();
    }
}

